package crmdna.common;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.junit.Test;

import crmdna.common.APIResponse.Status;

public class UtilsTest {
	@Test
	public void getQSTagsTest() {

		// Set<String> qsTags = Utils.getQSTags("sathyanarayanant@gmail.com",
		// "sathyanarayanan", "thilakan", "98361844", null, "65227030");
		Set<String> qsTags = Utils.getQSTags("sathyanarayanant@gmail.com",
				"Sathyanarayanan", "thilakan", null, null);

		Set<String> expected = new TreeSet<>();
		expected.add("sat");
		expected.add("ath");
		expected.add("thy");
		expected.add("hya");
		expected.add("yan");
		expected.add("ana");
		expected.add("nar");
		expected.add("ara");
		expected.add("ray");
		expected.add("aya");
		expected.add("yan");
		expected.add("ana");
		expected.add("nan");
		expected.add("ant");
		expected.add("nt@");
		expected.add("t@g");
		expected.add("@gm");
		expected.add("gma");
		expected.add("mai");
		expected.add("ail");
		expected.add("il.");
		expected.add("l.c");
		expected.add(".co");
		expected.add("com");

		// thilakan
		expected.add("thi");
		expected.add("hil");
		expected.add("ila");
		expected.add("lak");
		expected.add("aka");
		expected.add("kan");

		assertTrue(qsTags.containsAll(expected));
		assertEquals(expected.size(), qsTags.size());
	}

	@Test
	public void isPresentInListCaseInsensitiveTest() {
		assertEquals(false, Utils.isPresentInListCaseInsensitive(null, null));

		assertEquals(false, Utils.isPresentInListCaseInsensitive(
				new ArrayList<String>(), null));

		assertEquals(false, Utils.isPresentInListCaseInsensitive(
				new ArrayList<String>(), ""));

		List<String> list = new ArrayList<String>();
		list.add("sathya");
		list.add("sowmya");
		list.add("balaji");

		assertEquals(true, Utils.isPresentInListCaseInsensitive(list, "sAthYa"));
		assertEquals(true, Utils.isPresentInListCaseInsensitive(list, "balaji"));
		assertEquals(true, Utils.isPresentInListCaseInsensitive(list, "SowmYa"));

		assertEquals(false,
				Utils.isPresentInListCaseInsensitive(list, "thilakan"));

	}

	@Test
	public void throwIncorrectSpecificationExceptionTest() {
		try {
			Utils.throwIncorrectSpecException("message 1");
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(
					"exception should be incorrect specification exception",
					Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED, ex.statusCode);
			assertEquals("message should be correct", "message 1",
					ex.userFriendlyMessage);
		}
	}

	@Test
	public void throwNotFoundExceptionTest() {
		try {
			Utils.throwNotFoundException("message 1");
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(
					"exception should be incorrect specification exception",
					Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
			assertEquals("message should be correct", "message 1",
					ex.userFriendlyMessage);
		}
	}

	@Test
	public void ensureValidPhoneNumberTest() {

		// cannot be null
		try {
			Utils.ensureValidPhoneNumber(null);
			assertTrue(false);
		} catch (APIException ex) {
			assertTrue(ex.statusCode == Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED);
		}

		// cannot be empty string
		try {
			Utils.ensureValidPhoneNumber("");
			assertTrue(false);
		} catch (APIException ex) {
			assertTrue(ex.statusCode == Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED);
		}

		// should start with +
		try {
			Utils.ensureValidPhoneNumber("914422590181");
			assertTrue(false);
		} catch (APIException ex) {
			assertTrue(ex.statusCode == Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED);
		}

		// valid singapore number
		Utils.ensureValidPhoneNumber("+6598361844"); // no exception
		Utils.ensureValidPhoneNumber("+6593232152"); // no exception
		Utils.ensureValidPhoneNumber("+6565227030"); // no exception

		// india phone numbers
		Utils.ensureValidPhoneNumber("+914422593926"); // no exception
		Utils.ensureValidPhoneNumber("+919841283881"); // no exception
		Utils.ensureValidPhoneNumber("+919819532634"); // no exception

		// australia phone numbers
		Utils.ensureValidPhoneNumber("+61469218170"); // no exception

		// US phone number
		Utils.ensureValidPhoneNumber("+19198894985"); // no exception
	}
	
	@Test public void ensureValidUrlTest() {
		assertTrue(false);
	}

	@Test
	public void ensureValidEmailTest() {

		// cannot be null
		try {
			Utils.ensureValidEmail(null);
			assertTrue(false);
		} catch (APIException ex) {
			assertTrue(ex.statusCode == Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED);
		}

		// cannot be empty string
		try {
			Utils.ensureValidEmail("");
			assertTrue(false);
		} catch (APIException ex) {
			assertTrue(ex.statusCode == Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED);
		}

		// cannot have special char
		try {
			Utils.ensureValidEmail("@@@sathya.com");
			assertTrue(false);
		} catch (APIException ex) {
			assertTrue(ex.statusCode == Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED);
		}

		// valid email addresses
		Utils.ensureValidEmail("123@sathya.com");
		Utils.ensureValidEmail("sathya.t@ishafoundation.org");
		Utils.ensureValidEmail("ramya.c@ishafoundation.org");
	}

	@Test
	public void isFormatInYYYYMMDD() {
		assertEquals(false, Utils.isFormatInYYYYMMDD(2));
		assertEquals(false, Utils.isFormatInYYYYMMDD(290394938));
		assertEquals(false, Utils.isFormatInYYYYMMDD(2013312));
		assertEquals(false, Utils.isFormatInYYYYMMDD(20130229));
		assertEquals(false, Utils.isFormatInYYYYMMDD(19000229));
		assertEquals(false, Utils.isFormatInYYYYMMDD(21000229));

		assertEquals(true, Utils.isFormatInYYYYMMDD(20140201));
		assertEquals(true, Utils.isFormatInYYYYMMDD(20140131));
		assertEquals(true, Utils.isFormatInYYYYMMDD(20131231));
		assertEquals(true, Utils.isFormatInYYYYMMDD(20140630));
	}

	@Test
	public void getDurationAsString() {
		int start;
		int end;

		// same start and end date
		start = 20130201;
		end = 20130201;
		assertEquals("1 Feb 13", Utils.getDurationAsString(start, end));

		// same month and year
		start = 20130201;
		end = 20130204;
		assertEquals("1 - 4 Feb 13", Utils.getDurationAsString(start, end));

		// different month same year
		start = 20130227;
		end = 20130304;
		assertEquals("27 Feb - 4 Mar 13", Utils.getDurationAsString(start, end));

		// different year
		start = 20131227;
		end = 20140104;
		assertEquals("27 Dec - 4 Jan 14", Utils.getDurationAsString(start, end));

		start = 2013123;
		end = 2013125;
		try {
			Utils.getDurationAsString(start, end);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
					ex.statusCode);
		}
	}

	@Test
	public void isValidPhoneNumberTest() {
		assertTrue(false);
	}

	@Test
	public void closeEnoughTest() {
		assertFalse(Utils.closeEnough(null, null));

		assertTrue(Utils.closeEnough("sathya", "sathya"));
		assertTrue(Utils.closeEnough("sathya", "sathyan"));
		assertTrue(Utils.closeEnough("sathya", "sathyanarayanan"));
		assertTrue(Utils.closeEnough("radhika", "radikaa"));
		assertTrue(Utils.closeEnough("thulasi", "tulasi"));

		assertFalse(Utils.closeEnough("sathya", "sowmya"));
		assertFalse(Utils.closeEnough("paramesh", "giridhar"));
		assertFalse(Utils.closeEnough("giridhar", "raadhika"));
		assertFalse(Utils.closeEnough("thulasidhar", "giridhar"));
		assertFalse(Utils.closeEnough("ramesh", "suresh"));
		assertFalse(Utils.closeEnough("sathya", "syamala"));
	}

	@Test
	public void geDateDiffTest() {
		assertEquals("5 seconds", Utils.getDateDiff(0, 5));
		assertEquals("1 minute(s)", Utils.getDateDiff(0, 65));
		assertEquals("2 minute(s)", Utils.getDateDiff(0, 110));
		assertEquals("30 minute(s)", Utils.getDateDiff(0, 1820));
		assertEquals("1 hour(s)", Utils.getDateDiff(0, 3800));
		assertEquals("3 hour(s)", Utils.getDateDiff(0, 11000));

		assertEquals("1 day(s)", Utils.getDateDiff(0, 3600 * 24));
		assertEquals("2 day(s)", Utils.getDateDiff(0, 3600 * 24 * 2 + 1200));
	}

	@Test
	public void toYYYYMMDDTest() {
		Calendar calendar = Calendar.getInstance();

		// 1-jan-2014
		calendar.set(2014, 0, 1); // month goes from 0 to 11
		assertEquals(20140101, Utils.toYYYYMMDD(calendar.getTime()));

		// 31-dec-1989
		calendar.set(1989, 11, 31); // month goes from 0 to 11
		assertEquals(19891231, Utils.toYYYYMMDD(calendar.getTime()));

		// 29-feb-2004
		calendar.set(2004, 1, 29); // month goes from 0 to 11
		assertEquals(20040229, Utils.toYYYYMMDD(calendar.getTime()));
	}

	@Test
	public void getFullNameTest() {
		assertEquals("Sathya Thilakan", Utils.getFullName("Sathya", "Thilakan"));
		assertEquals("Sathya", Utils.getFullName("Sathya", null));
		assertEquals("Thilakan", Utils.getFullName(null, "Thilakan"));
		assertEquals(null, Utils.getFullName(null, null));
	}
	
	@Test public void toDateTest() {
		assertTrue(false);
	}
	
	@Test public void getNumDaysTest() {
		assertTrue(false);
	}

	@Test
	public void ensureNonNegativeTest() {
		Utils.ensureNonNegative(0); // no exception
		Utils.ensureNonNegative(10.09384); // no exception

		try {
			Utils.ensureNonNegative(-10);
			assertTrue(false);
		} catch (APIException e) {
			assertEquals(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
					e.statusCode);
		}
	}

	@Test
	public void asCurrencyStringTest() {
		assertEquals("150.00", Utils.asCurrencyString(150));
		assertEquals("150.55", Utils.asCurrencyString(150.546));
		assertEquals(".50", Utils.asCurrencyString(0.501));
	}

	@Test
	public void safeParseAsLongTest() {
		assertEquals(100, Utils.safeParseAsLong("100"));
		assertEquals(-100, Utils.safeParseAsLong("-100"));
		assertEquals(0, Utils.safeParseAsLong("0"));

		try {
			Utils.safeParseAsLong("abc");
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
					ex.statusCode);
		}
		
		try {
			Utils.safeParseAsLong("100.23");
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
					ex.statusCode);
		}
	}
	
	@Test
	public void safeParseAsIntTest() {
		assertEquals(100, Utils.safeParseAsInt("100"));
		assertEquals(-100, Utils.safeParseAsInt("-100"));
		assertEquals(0, Utils.safeParseAsInt("0"));

		try {
			Utils.safeParseAsInt("abc");
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
					ex.statusCode);
		}
		
		try {
			Utils.safeParseAsInt("100.23");
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
					ex.statusCode);
		}				
	}
	
	@Test
	public void safeParseAsDouble() {		
		assertTrue(100 == Utils.safeParseAsDouble("100"));
		assertTrue(100 == Utils.safeParseAsDouble("100.00"));
		assertTrue(-100 == Utils.safeParseAsDouble("-100"));
		assertTrue(-100.098 == Utils.safeParseAsDouble("-100.098"));
		assertTrue(0 == Utils.safeParseAsDouble("0"));

		try {
			Utils.safeParseAsDouble("abc");
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
					ex.statusCode);
		}		
	}
	
	@Test public void urlEncodeTest() {
		assertTrue(false);
	}
	
	@Test public void getUrlTest() {
		
		String baseUrl = "http://www.google.com";
		
		Map<String, Object> map = new HashMap<>();
		map.put("firstName", "sathya");
		map.put("programType", "Surya Kriya");
		map.put("program Id", new Long(6));
		map.put("alreadyRegistered", true);
		
		String url = Utils.getUrl(baseUrl, map);
		assertEquals("http://www.google.com?alreadyRegistered=true&firstName=sathya&program%20Id=6&programType=Surya%20Kriya&", url);		
	}
	
	@Test public void ensureNotNullOrEmptyTest() {
		assertTrue(false);
	}
	
	@Test public void ensureNonZeroTest() {
		assertTrue(false);
	}
	
	@Test public void csvEncodeTest() {
		assertTrue(false);
	}
	
	@Test public void sanitizePhoneNoTest() {
		assertTrue(false);
	}
	
	@Test public void sanitizeEmailTest() {
		assertTrue(false);
	}
	
	@Test public void toUserFriendlyStringTest() {
		assertTrue(false);
	}
}
